/**
 * @Project : algorithm-learning
 * @Author : Ruoyu Wang
 * @User : Momenta
 * @DateTime : 2024/3/21 17:57
 */

//小苯有一个疑问，如果一个宿舍有n个人，编号从1到n，且有些人之间是好朋友，必须同时在一个群或不在一个群。
//在这样的情况下，宿舍最多能建几个不同的群聊（答案对1000000007取模）。
//注：
//1.小苯认为一个人不能建群，也就是说群聊人数必须大于1。
//2.定义两个群聊不同，当且仅当存在至少一个人，此人在其中一个群聊而不在另一个群聊。
//
//输入描述
//  输入包含m+1行。
//  第一行两个正整数n,m,(1<=n,m<=2*10^5)，分别表示宿舍的人数和好朋友关系数量。
//  接下来m行，每行两个正整数u,v,(1<=u,v<=n)且(u!=v)，代表u,v两人是一对好朋友，必须同时在一个群聊里或同时不在一个群聊里。
//
//输出描述
//  输出包含一行表示不同群聊的方案数对1000000007取模后的值。
//
//示例1
//输入
//5 2
//1 2
//2 3
//输出
//5
//说明
//  宿舍有5个人，1和2是好朋友，2和3是好朋友，他们必须同时在或不在一个群里。
//  可以建：{1,2,3},{1,2,3,4},{1,2,3,5},{4,5},{1,2,3,4,5}这5个不同的群聊。
//
//示例2
//输入
//8 4
//1 2
//2 4
//3 5
//6 8
//输出
//14

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int MOD = 1000000007;
const int N = 200010;
vector<vector<int>> edges(N);
bool st[N];

void dfs(int node, int &size) {
    st[node] = true;
    size++;
    for (int p: edges[node]) {
        if (!st[p]) {
            dfs(p, size);
        }
    }
}

long long qmi(long long a, int k) {
    long long res = 1;
    while (k) {
        if (k & 1) res = (res * a) % MOD;
        k >>= 1;
        a = (a * a) % MOD;
    }
    return res;
}

int main() {
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 0; i < q; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        edges[u].push_back(v);
        edges[v].push_back(u);
    }

    long long result;
    int sum = 0;
    int del = 0;
    for (int i = 1; i <= n; i++) {
        if (!st[i]) {
            int size = 0;
            dfs(i, size);
            sum++;
            if (size == 1) del++;
        }
    }
    result = ((qmi(2, sum) - del - 1) + MOD) % MOD;
    printf("%lld\n", result);
    return 0;
}